#ifndef __BAN_MANAGER_H__
#define __BAN_MANAGER_H__

#include <cstdint>
#include <memory>
#include <set>
#include <string>

#include "Engine/GameGuid.h"
#include "SimpleSingleton.hpp"
#include "GameLock.hpp"


using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    class ServerRoot;

    /**
     * 单独封禁玩家的话，是使用 guid 来区分对应的玩家
     * 封禁ip的话，是先将ip转换成字符串，然后再对比字符串的
    */

    class BanManager : public SimpleSingletonItem
    {
        friend class SimpleSingleton;

    private:
        std::set<GameGuid> m_banGuidSet;
        SpinLock m_banGuidSetMutex;

        std::set<std::string> m_banIpSet;
        SpinLock m_banIpSetMutex;
    private:
        BanManager();
        ~BanManager();
        BanManager(const BanManager &) = delete;
        BanManager(BanManager &&) = delete;
        BanManager &operator=(const BanManager &) = delete;
        BanManager &operator=(BanManager &&) = delete;

    public:
        /**
         * @brief 封禁玩家
         * @param guid 玩家的 guid
        */
        void addBanGuid(const GameGuid &guid);

        /**
         * @brief 移除被封禁的玩家
         * @param guid 被封禁的玩家
         * @return true:解封成功，false:该玩家没有被封禁
        */
        bool removeBanGuid(const GameGuid &guid);

        /**
         * @brief 判断玩家是否被封禁
         * @param guid 玩家的guid
         * @return true:该玩家是被封禁的，false:该玩家没在封禁列表里面
        */
        bool guidIsInBanSet(const GameGuid &guid);
        
        /**
         * @brief 封禁 IP
         * @param ipStr IP字符串，不要带端口，带端口的话基本等于无用
         * @note 封禁 IP 不会对在该 IP 下的客户端进行额外的封禁，但是会断开所有该 IP 的客户端
        */
        void addBanIp(const std::string &ipStr);

        /**
         * @brief 解除 IP 的封禁
         * @param ipStr IP字符串
         * @return true:解除成功，false:该IP没有被封禁
        */
        bool removeBanIp(const std::string &ipStr);

        /**
         * @brief 判断 IP 是否是被封禁
         * @param ipStr IP字符串
         * @return true:该IP是被封禁的，false:IP没有被封禁
        */
        bool ipIsInBanSet(const std::string &ipStr);

        /**
         * @brief 读取本地文件里面的封禁数据
         * @note 读取的时候会清理掉运行过程中的数据，然后再读取本地文件里面的封禁数据
        */
        void load();

        /**
         * @brief 将封禁的数据保存到本地文件 (Server/ban.json) 中
        */
        void save();
    };


} // namespace PocketSurvival

#endif
